package com.ls.fw.data.search.impl.lucene.parser;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;

import com.ls.fw.common.beanparser.bean.FromInfo;
import com.ls.fw.common.beanparser.schema.Column;
import com.ls.fw.common.beanparser.schema.Expression;
import com.ls.fw.common.beanparser.statement.Select;
import com.ls.fw.common.beanparser.visitor.ColumnVisitor;
import com.ls.fw.common.beanparser.visitor.ExpressionVisitor;
import com.ls.fw.common.beanparser.visitor.FromVisitor;


public class SelectParser implements ColumnVisitor,ExpressionVisitor,FromVisitor{

	private StringBuilder sql = new StringBuilder();
	private StringBuilder countSql = new StringBuilder();
	private Query query = new BooleanQuery();
	private boolean first = true;
	private String split = ",";
	private Map<String,Object> value = new HashMap<String,Object>();
	
	public SelectParser(Select select){
		sql.append("SELECT ");
		countSql.append("SELECT count(1) AS count ");
		List<Column> list = select.getFieldInfo().getColumnList();
		boolean hasField = false;
		if(!select.getFieldInfo().isEmpty()){
			for (Column object : list) {
				object.accept(this);
				hasField = true;
			}
		} 
		List<Expression> list1 = select.getFieldInfo().getList();
		if(!select.getFieldInfo().isEmpty()){
			for (Expression object : list1) {
				object.accept(this);
				hasField = true;
			}
		} 
		if(!hasField){
			sql.append("*");
		}
		select.getFromInfo().accept(this);
		//where
		WhereParser w = new WhereParser(select.getWhereInfo());
		sql.append(w.getSql());
		countSql.append(w.getSql());
		query = w.getQuery();
		value.putAll(w.getValue());
		
		OrderParser o = new OrderParser(select.getOrderInfo());
		sql.append(o.getSql());
	}
	
	@Override
	public void visit(Column column) {
		if(!first){
			sql.append(split);
		}
		sql.append(column.getFullName());
		String  a = column.getAlias();
		if(a!=null && !"".equals(a)){
			sql.append(" AS "+a);
		}
		first = false;
	} 

	@Override
	public void visit(FromInfo fromInfo) {
		// TODO Auto-generated method stub
		StringBuilder from = new StringBuilder();
		from.append(" FROM "+fromInfo.getTable().getWholeTableName());
		String  a = fromInfo.getTable().getAlias();
		if(a!=null && !"".equals(a)){
			from.append(" AS "+a);
		}else{
			a = fromInfo.getTable().getWholeTableName();
		}
		if(fromInfo.getTable1()!=null){
			
			from.append(" "+ fromInfo.getJoinType().getName()+" ");
			from.append(" "+fromInfo.getTable1().getWholeTableName());
			String  a1 = fromInfo.getTable1().getAlias();
			if(a1!=null && !"".equals(a1)){
				from.append(" AS "+a1);
			}else{
				a1 = fromInfo.getTable1().getWholeTableName();
			}
			from.append(" ON ");
			from.append(a+"."+fromInfo.getHostJoinColumnName()+"="+a1+"."+fromInfo.getJoinColumnName());
		}
		this.sql.append(from);
		this.countSql.append(from);
	}
	
	//select count(id)等
	@Override
	public void visit(Expression expression) {
		if(expression.getFunction()!=null){
			
			if(!first){
				sql.append(split);
			} 
			sql.append(this.getF(expression));
			String  a = expression.getAlias();
			if(a!=null && !"".equals(a)){
				sql.append(" AS "+a);
			}else{
				sql.append(" AS "+expression.getFunction().getName()+"_"+expression.getName());
			}
			first = false;
		}
	}

	private String getF(Expression expression){
		StringBuilder sql = new StringBuilder();
		sql.append(expression.getFunction().getName());
		sql.append("(");
		Object[] p = expression.getFunction().getParas();
		if(p!=null){
			sql.append(StringUtils.join(p));
		}
		sql.append(")");
		return sql.toString();
	}

	public void setSql(StringBuilder sql) {
		this.sql = sql;
	}

	public StringBuilder getSql() {
		return sql;
	}

	public void setValue(Map<String,Object> value) {
		this.value = value;
	}

	public Map<String,Object> getValue() {
		return value;
	}

	public StringBuilder getCountSql() {
		return countSql;
	}

	public void setCountSql(StringBuilder countSql) {
		this.countSql = countSql;
	}

	public Query getQuery() {
		return query;
	}

	public void setQuery(Query query) {
		this.query = query;
	}
}
